import re
import random
import io
import datetime
import jwt
import json
import logging

from django.views import View
from django.http import HttpResponse,JsonResponse
from django.utils.decorators import method_decorator
from django.core.mail import send_mail
from django_redis import get_redis_connection
from django.contrib.auth.hashers import check_password,make_password
from django.core.serializers import serialize
from fdfs_client.client import get_tracker_conf,Fdfs_client

from apps.user.models import User,UserDetail
from conf import token_conf
from qqmall.settings import EMAIL_HOST_USER,FASTDFS_SERVER_DOMAIN
from utils.resFormatUyil import FormatResponse
from utils.verifyUtil import verfy_params,Image_verify
from celery_tasks.email.tasks import send_mail_task


EMAIL_KEY = 'email:%s'
EXPIRY = 1
LOGIN_KEY = 'login:verify:%s'

IMAGE_VERIFY = 'img_veridy:%s'

# 实现获取验证码的功能
class VerifyEmailView(View):
    @method_decorator(verfy_params('email'))
    def post(self,request):
        # 获取邮箱
        email = request.POST.get('email')
        # 验证邮箱格式是否正确
        format = r'(\w+)@(\w+)\.(\w+)'
        if not re.match(format,email):
            return FormatResponse(status='PARAM_ERROR').res()
        # 邮箱格式正确，判断该邮箱账号一分钟内是否发送过请求
        cache_default = get_redis_connection()
        if cache_default.get(EMAIL_KEY%email):
            return FormatResponse(status='ACCESS_RESTRICTION').res()
        # 生成随机验证码
        random_code = random.randint(100000,999999)
        # 发送验证码
        send_mail_task.delay(email=email,random_code=random_code,expiry=EXPIRY)
        return FormatResponse().res()


# 实现注册功能
class RegisterView(View):
    # 注册功能需传递邮箱账号，验证码，密码
    @method_decorator(verfy_params('email','verify','password'))
    def post(self,request):
        # 获取相关参数
        email = request.POST.get('email')
        verify = request.POST.get('verify')
        password = request.POST.get('password')
        # 验证邮箱格式是否正确
        format = r'(\w+)@(\w+)\.(\w+)'
        if not re.match(format, email):
            return FormatResponse(status='PARAM_ERROR').res()
        # 查看该邮箱是否已经被注册,若已注册返回已注册信息
        if User.objects.filter(email=email):
            return FormatResponse(status='ACCOUNT_REGISTRATION').res()
        # 查看验证码是否正确
        cache = get_redis_connection()
        if (not cache.get(EMAIL_KEY % email)) or (cache.get(EMAIL_KEY % email) != verify):
            return FormatResponse(status='PARAM_ERROR').res()
        # 将用户信息保存到数据库当中
        User.objects.create(email=email,password=make_password(password))
        # 注册成功，删除验证码，缓解内存压力
        cache.delete(EMAIL_KEY % email)
        return FormatResponse().res()


# 登录界面的验证码功能
class ImageVerificationView(View):
    def get(self,request,uuid):
        # 获取验证码和验证码图像
        code,img = Image_verify().image_code()
        # 将验证码保存到redis数据库中
        cache = get_redis_connection(alias='verify_code')
        cache.set(LOGIN_KEY % uuid,code,60)
        # 生成二进制临时文件
        box = io.BytesIO()
        img.save(box,format='png')
        # 取出二进制验证码图片
        img = box.getvalue()
        return HttpResponse(img,content_type='image/png')


# 登录功能
class LoginView(View):
    # 注册功能需传递邮箱账号，验证码，密码
    @method_decorator(verfy_params('email', 'verify', 'password'))
    def post(self,request,uuid):
        # 获取相关参数
        email = request.POST.get('email')
        verify = request.POST.get('verify')
        password = request.POST.get('password')
        # 判断该邮箱账号是否已经注册，如果没有注册返回限制访问
        user = User.objects.filter(email=email,state=0)
        if not user:
            return FormatResponse(status='ACCESS_RESTRICTION').res()
        # 判断密码是否正确
        if not check_password(password,user[0].password):
            return FormatResponse(status='PARAM_ERROR').res()
        # 判断验证码是否则正确
        cache = get_redis_connection(alias='verify_code')
        cache_value = cache.get(LOGIN_KEY % uuid)
        if (not cache_value) or (cache_value.lower() != verify.lower()):
            return FormatResponse(status='PARAM_ERROR').res()
        # 验证成功，生成令牌
        payload = {
            'iss': 'LoginView_post',
            'sub': 'login',
            'iat': int(datetime.now().timestamp()),
            'exp': datetime.now() + datetime.timedelta(days=1),
            # 'exp': int(datetime.now().timestamp()) + 30,
            'data': email,
        }
        encode_jwt = jwt.encode(payload, token_conf.TOKEN_SECRET_KEY, algorithm=token_conf.ALGORITHM,
                                headers=token_conf.headers)
        print(encode_jwt)
        # 后台向前端发送令牌信息，前端用来保存
        return FormatResponse(data=encode_jwt).res()


# 用户信息功能
class UserDetailView(View):
    # 获取用户信息
    def get(self,request):
        # 获取邮箱账号
        email = request.email
        # 获取用户对象
        user_query = User.objects.filter(email=email,state=0)
        # 没有获取到对象则报错
        if not user_query:
            return FormatResponse(status='UNKNOWN_ERROR').res()
        user = user_query[0]
        try:
            user_detail = user.detail
        except:
            user_detail = UserDetail()
            user_detail.user = user
            user_detail.save()
        # 序列化处理
        user_detail = json.loads(serialize('json',[user_detail],ensure_ascii=False))
        data = {
            'email':email,
            'user_detail':user_detail[0]['fields']
        }
        return FormatResponse(data=data).res()

    # 修改用户信息
    def post(self,request):
        # 获取用户的邮箱账号
        email = request.email
        # 获取用户对象
        user = User.objects.get(email=email,state=0)
        try:
            user_detail = user.detail
        except:
            user_detail = UserDetail()
            user_detail.user = user
        user_detail.nickname = request.POST.get('nickname')
        user_detail.phone = request.POST.get('phone')
        user_detail.age = request.POST.get('age')
        user_detail.sex = request.POST.get('sex')
        user_detail.birthday = request.POST.get('birthday')
        user_detail.adddress = request.POST.get('adddress')
        user_detail.save()
        return FormatResponse().res()


# 配置tracker配置信息的路径
tracker_path = get_tracker_conf('utils/fastdfs/client.conf')
# 开启客户端
client = Fdfs_client(tracker_path)

# 导入日志器
loger = logging.getLogger(__name__)

# 头像上传功能
class PortraitView(View):
    def post(self,request):
        # 获取上传的文件
        file = request.FILES.get('file')
        # 校验文件是否存在或者文件格式是否正确
        if (not file) or (file.content_type not in ('image/jpg','image/png','iamge/jpeg')):
            return FormatResponse(status='PARAM_ERROR').res()
        # 获取文件的后缀，比如png,jpg,获取失败就造个png
        try:
            file_ext_name = file.name.split('.')[-1]
        except Exception as e:
            loger.warning(f'图片后缀名获取错误，错误信息为{e}')
            file_ext_name = 'png'
        # 将用户上传给后端的文件上传到fastdfs服务器上
        try:
            res = client.upload_by_buffer(file.read(),file_ext_name=file_ext_name)
        except Exception as e:
            loger.error(f'图片上传异常，错误信息：{e}')
            return FormatResponse(status='UPLOAD_EXCEPTION').res()
        else:
            # 查看图片上传成功后的响应结果是否异常
            if res.get('Status') != 'Upload successed.':
                return FormatResponse(status='UPLOAD_EXCEPTION').res()
            # 上传成功，获取图片在服务端的保存地址
            img_url = FASTDFS_SERVER_DOMAIN + res.get('Remote file_id').decode()
            # 将图片地址保存到数据库当中
            user = User.objects.get(eamil=request.email,state=0)
            # 没有获取到用户则报错
            if not user:
                return FormatResponse(status='UNKNOWN_ERROR').res()
            try:
                user_detail = user.detail
            except:
                user_detail = UserDetail()
                user_detail.user = user
            user_detail.portrait = img_url
            user_detail.save()
        return FormatResponse(data=img_url).res()

















